// 9.3 顺序容器操作
/**
 * 顺序容器和关联容器的不同之处在于两者组织元素的方式。这些不同之处直接关系到了元素如何存储、访问、添加以及删除。
 *
 * 9.3.2 访问元素
 * 包括array在内的每个顺序容器都有一个front成员函数，而除forward_list之外的所有顺序容器都有一个back成员函数。
 * 这两个操作分别返回首元素和尾元素的引用
 */

#include <vector>
#include <list>
#include <deque>
#include <forward_list>
#include <string>
#include <array>
using std::swap;
using std::vector, std::list, std::deque, std::forward_list, std::string, std::array;
#include "../Chapter07/Sales_data.h"
#include <iostream>
using std::cin, std::cout, std::endl;

int main()
{
    // front和back成员
    /**
     * 包括array在内的每个顺序容器都有一个front成员函数，而除forward_list之外的所有顺序容器都有一个back成员函数。
     * 这两个操作分别返回首元素和尾元素的引用
     */
    forward_list<int> c;
    if (!c.empty()) // 在解引用一个迭代器或调用front、back之前检查是否有元素
    {
        // val1和val2是c中第一个元素值的拷贝
        auto val1 = *c.begin(), val2 = c.front();
        // val3和val4是c中最后一个元素值的拷贝
        auto last = c.end();
        auto val3 = *(--last); // 不能递减forward_list的迭代器
        auto val4 = c.back();  // forward_list不支持back
    }

    // 访问呢成员函数返回的是引用
    /**
     * 在容器中访问元素的成员函数（即，front、back、下标和at）返回的都是引用。如果容器是一个const对象，则返回值是const的引用。
     * 如果容器不是const的，则返回值是普通引用，我们可以用来改变元素的值。
     */
    list<int> c1;
    if (!c1.empty())
    {
        c1.front() = 42;     // 将42赋值给c中第一个元素
        auto &v = c1.back(); // 获取指向最后一个元素的引用
        auto v2 = c1.back(); // v2不是引用，它是c1.back()的一个拷贝
        v2 = 0;              // 未改变c1中的值
    }

    // 下标操作和安全的随机访问
    /**
     * 提供快速随机访问的容器（string、vector、deque和array）也都提供下标运算符（参见3.3.3节，第91页）。
     * 如果我们希望确保下标是合法的，可以使用at成员函数。at成员函数类似下标运算符，
     * 但如果下标越界，at会抛出一个out_of_range异常（参见5.6节，第173页）。
     */
    vector<string> svec1;
    cout << svec1[0];    // 运行时错误，svec1中没有元素
    cout << svec1.at(0); // 抛出一个out_of_range异常

    

    return 0;
}